#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <curl/curl.h>
#include <iomanip>
#include <iostream>
#include <nlohmann/json.hpp>
#include <string>
#include <vector>

int width = 3;
int length = 3;
int smoothCount = 5;

float totalHeight = 0.0f;
int totalWA = 0, totalSA = 0, totalFR = 0, totalPL = 0, totalMT = 0, totalSM = 0;

using namespace std;
using json = nlohmann::json;

const string APIKEY = "abb0a03580e240b199982f226441edd9.7zBPbB6iMu0ENxsB";

// 保留2位小数
string roundFloat(float value, int decimalPlaces = 2) {
    stringstream ss;
    ss << fixed << setprecision(decimalPlaces) << value;
    return ss.str();
}

// 回调函数
size_t writeCallback(void* contents, size_t size, size_t nmemb, void* userp) {
    ((string*)userp)->append((char*)contents, size * nmemb);
    return size * nmemb;
}

// 调用智谱清言
// messages是对话记录。temporaryPrompt是临时提示，只在本轮对话中使用。
string tellZhipu(vector<json>& messages, json temporaryPrompt) { // 修改点2：参数类型变更
    CURL* curl = curl_easy_init();
    CURLcode res;
    string readBuffer;
    vector<json> fullMessages = messages;

    fullMessages.push_back(temporaryPrompt);

    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, "https://open.bigmodel.cn/api/paas/v4/chat/completions");

        struct curl_slist* headers = nullptr;
        headers = curl_slist_append(headers, "Content-Type: application/json");
        headers = curl_slist_append(headers, ("Authorization: Bearer " + APIKEY).c_str());
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

        json root; // 修改点3：使用nlohmann::json对象
        root["model"] = "glm-4-plus";
        root["messages"] = fullMessages; // 直接赋值vector

        // 在发送请求前添加调试输出
        cout << "\n=== 发送的请求数据 ===" << endl;
        cout << root.dump(2) << endl;                                              // 带缩进的JSON输出
        string output = root.dump(-1, ' ', false, json::error_handler_t::replace); // 修改后的安全输出

        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, output.c_str());
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);

        res = curl_easy_perform(curl);
        if (res != CURLE_OK)
            cerr << "curl_easy_perform()失败: " << curl_easy_strerror(res) << endl;

        curl_easy_cleanup(curl);
        curl_slist_free_all(headers);
    }
    return readBuffer;
}

// 处理响应
void processResponse(const string& response, vector<json>& messages) {
    try {
        // 添加原始响应输出
        cout << "\n=== 原始响应数据 ===" << endl;
        cout << "响应长度: " << response.length() << "字节" << endl;
        cout << "前200字符: " << response.substr(0, 200) << endl;

        // 添加十六进制查看（检测0xAF等非法字符）
        cout << "十六进制示例: ";
        for (int i = 0; i < 50 && i < response.size(); ++i) {
            cout << hex << setw(2) << setfill('0') << (int)(unsigned char)response[i] << " ";
        }
        cout << dec << endl;

        json root = json::parse(response); // 修改点5：使用parse替代Reader

        if (root.contains("choices") && root["choices"].is_array()) {
            for (const auto& choice : root["choices"]) {
                if (choice.contains("message")) {
                    json message = choice["message"];
                    messages.push_back(message);
                    cout << "助手: " << message["content"].get<string>() << endl; // 修改点6：类型安全获取
                }
            }
        } else {
            cerr << "意外响应格式" << endl;
        }
    } catch (const json::exception& e) { // 修改点7：异常处理
        cerr << "JSON解析错误: " << e.what() << endl;
    }
}

// 生成随机高度图
void generateHeightmap(vector<vector<float>>& heightmap) {
    // 初始化随机种子
    srand(static_cast<unsigned>(time(nullptr)));

    // 生成初始随机高度
    for (int y = 0; y < length; ++y) {
        for (int x = 0; x < width; ++x) {
            heightmap[y][x] = static_cast<float>(rand()) / RAND_MAX;
            totalHeight += heightmap[y][x];
        }
    }

    // 简单平滑处理（模拟自然侵蚀）
    for (int i = 0; i < smoothCount; ++i) {
        for (int y = 1; y < length - 1; ++y) {
            for (int x = 1; x < width - 1; ++x) {
                heightmap[y][x] = (heightmap[y][x] + heightmap[y - 1][x] + heightmap[y + 1][x] + heightmap[y][x - 1] +
                                   heightmap[y][x + 1]) /
                                  5.0f;
            }
        }
    }
}

// 根据高度转换为地形
string heightToString(float height) {
    if (height < 0.3) {
        totalWA++;
        return "水域";
    }
    if (height < 0.35) {
        totalSA++;
        return "沙滩";
    }
    if (height < 0.6) {
        // 在平原有30%概率生成森林
        if ((rand() % 100) < 30) {
            totalFR++;
            return "森林";
        }
        totalPL++;
        return "平原";
    }
    if (height < 0.8) {
        totalMT++;
        return "山脉";
    }
    totalSM++;
    return "雪山";
}

json generateGameMapJson(vector<vector<float>>& heightmap) {
    json gameMap;

    json mapArray = json::array();
    for (int y = 0; y < length; ++y) {
        for (int x = 0; x < width; ++x) {
            string terrain = heightToString(heightmap[y][x]);

            json tile = {{"x", x + 1},
                         {"y", y + 1},
                         {"terrain", terrain},
                         {"height", roundFloat(heightmap[y][x])},
                         {"desc", terrain == "水域"   ? "清澈的蓝色水域"
                                  : terrain == "沙滩" ? "松软的金色沙滩"
                                  : terrain == "平原" ? "肥沃的平原地带"
                                  : terrain == "森林" ? "茂密的绿色森林"
                                  : terrain == "山脉" ? "高耸陡峭的山脉"
                                                      : "终年积雪的雪山"}};
            mapArray.push_back(tile);
        }
    }
    gameMap["map"] = mapArray;

    // 元数据
    gameMap["metadata"] = {{"size", {width, length}}};
    /*
    gameMap["stats"] = {{"water", totalWA},  {"sand", totalSA},     {"plain", totalPL},
                        {"forest", totalFR}, {"mountain", totalMT}, {"snow_mountain", totalSM}};
    float avgHeight = roundFloat(totalHeight / (width * length), 2);
    {{"avg_height", avgHeight},
    */

    return gameMap;
}

int main() {

    // cout << "图例:水域WA,沙滩SA,平原PL,森林FR,山脉MT,雪山SM" << endl;
    //  设置地图大小和迭代次数
    cout << "请输入:地图宽 地图高 平滑迭代次数：";
    cin >> width >> length >> smoothCount;

    // 初始化二维数组
    vector<vector<float>> heightmap(length, vector<float>(width));
    generateHeightmap(heightmap);

    // 创建JSON对象
    json gameMap;
    gameMap = generateGameMapJson(heightmap);

    cout << setw(2) << gameMap << endl;

    json presentGameInfo;

    // 游戏内容
    json mapAgentPrompt;
    mapAgentPrompt["role"] = "system";
    mapAgentPrompt["content"] = "你是一个地图AI，你可以回答关于地图的问题。";

    vector<json> messages;
    string userInput, response;
    json userContent, presentPrompt;

    // 告诉AI角色
    messages.push_back(mapAgentPrompt);

    presentPrompt["role"] = "user";

    while (true) {

        // 问AI问题
        cout << "用户: ";
        cin.ignore();
        getline(cin, userInput);
        if (userInput == "exit")
            break;

        presentPrompt["content"] = "地图数据：" + gameMap.dump(-1, ' ', false, json::error_handler_t::replace) +
                                   "\n问题：" + json(userInput).dump(-1, ' ', false, json::error_handler_t::replace);

        // AI回答
        response = tellZhipu(messages, presentPrompt);

        // 保存用户问题,其余不保留
        userContent["role"] = "user";
        userContent["content"] = json(userInput).dump(-1, ' ', false, json::error_handler_t::replace);
        messages.push_back(userContent);

        processResponse(response, messages);
    }

    return 0;
}